package cn.wolfcode.luowowo.website.controller;

import cn.wolfcode.luowowo.cache.service.impl.impl.IUserInfoCacheService;
import cn.wolfcode.luowowo.cache.service.impl.impl.IVerifyCodeCacheService;
import cn.wolfcode.luowowo.common.util.AjaxResult;
import cn.wolfcode.luowowo.common.util.Consts;
import cn.wolfcode.luowowo.member.service.IUserInfoService;
import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.UUID;

/**
 * 登录注册相关的功能
 */
@Controller
public class LoginController {

    @Reference//远程引入用户信息服务
    private IUserInfoService userInfoService;

    @Reference//远程引入验证码服务
    private IVerifyCodeCacheService verifyCodeCacheService;

    @Reference//远程引入缓存用户信息服务
    private IUserInfoCacheService userInfoCacheService;

    /**
     * 1. 当用户发起登录请求时，先校验用户信息，判断是否登录成功
     * 2. 在分布式应用中往往都会做集群，所以单单的依靠把信息存入session是不够的，
     * 在登录成功后不仅需要把登录对 象信息存入session，还需要把登录对象的信息存入redis
     * <p>
     * 资源：  /userLogin 参数：  phone=xxx  password=xxx
     * 返回：  {    success: true / false    msg: xxx（错误信息）  }
     */
    @ResponseBody
    @RequestMapping("/userLogin")
    public Object userLogin(String phone, String password, HttpSession session, HttpServletResponse response) {

        //根据账号密码从数据库查询
        AjaxResult result = userInfoService.userLogin(phone, password);

        if (result.isSuccess()) {
            Object userInfo = result.getData();
            //1.将用户信息添加到本地Session
            session.setAttribute(Consts.USER_INFO, userInfo);
            //Redis的token
            String token = UUID.randomUUID().toString().replaceAll("-", "");
            //2.将用户信息添加到Redis
            userInfoCacheService.setUserInfoCache(token, JSON.toJSONString(userInfo));

            //3.创建一个Cookies,返回给客户端
            Cookie cookie = new Cookie(Consts.USER_INFO_TOKEN, token);
            //设置作用域
            cookie.setPath("/");
            //通过参数注入HttpServletResponse给浏览器添加cookies
            //cookies携带key,用于查询redis中用户的信息
            response.addCookie(cookie);

        }

        return result;
    }

    /**
     * 生成验证码存储到Redis中
     * <p>
     * 资源：  /sendVerifyCode
     * 参数：  phone=xxx
     * 返回：  {    success: true / false    msg: xxx（错误信息）  }
     */
    @ResponseBody
    @RequestMapping("/sendVerifyCode")
    public Object sendVerifyCode(String phone) {

        AjaxResult result = new AjaxResult();

        try {
            //如果redis中的验证码没有过期,提示用户验证码已经发送
            if (verifyCodeCacheService.getVerifyCode(phone) != null) {
                return result.mark("验证码已经发送,请勿重复点击!");
            }

            //模拟生成验证码
            String verifyCode = UUID.randomUUID().toString().substring(0, 4);

            //存入redis
            verifyCodeCacheService.setVerifyCode(phone, verifyCode);

            //从redis取出
            System.err.println(verifyCodeCacheService.getVerifyCode(phone));
        } catch (Exception e) {
            e.printStackTrace();
            result.mark(e.getMessage());
        }

        return result;
    }

    /**
     * 后台接收到信息后必须先进行数据合法性校验，如：非空，两次密码输入是否一致等
     * 验证通过后需要填充用户的默认数据（性别，等级，城市等），然后保存用户信息
     * 资源： /userRegist
     * 参数： phone=xxx nickname=xxx password=xxx rpassword=xxx verifyCode=xxx(该参数前期先忽略)
     * 返回： { success: true / false msg:xxx（错误信息） }
     */
    @RequestMapping("/userRegist")
    @ResponseBody
    public Object userRegist(String phone, String nickname, String password, String rpassword, String verifyCode) {
        return userInfoService.userRegist(phone, nickname, password, rpassword, verifyCode);
    }

    /**
     * 后台查询数据库该手机号码是否存在，返回校验结果
     * <p>
     * 资源： /checkPhone
     * 参数： phone=xxx
     * 返回： true -> 可以注册 false -> 已经注册
     */
    @RequestMapping("/checkPhone")
    @ResponseBody
    public Object checkPhone(String phone) {
        return userInfoService.checkPhone(phone);
    }

}
